package deptConfig

import (
	"context"
	"devops-super/api"
	"devops-super/api/configs/v1"
	"devops-super/internal/consts/cacheConsts"
	"devops-super/internal/dao"
	"devops-super/internal/model/entity"
	"devops-super/internal/service"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
)

// sDeptConfig 部门配置逻辑实现
type sDeptConfig struct{}

func init() {
	service.RegisterDeptConfig(New())
}

// New 创建部门配置逻辑实例
func New() *sDeptConfig {
	return &sDeptConfig{}
}

// Add 添加部门配置
func (*sDeptConfig) Add(ctx context.Context, in *entity.DeptConfig) (id uint64, err error) {
	// 检查配置是否已存在
	count, _ := dao.DeptConfig.Ctx(ctx).
		Where(dao.DeptConfig.Columns().DeptId, in.DeptId).
		Where(dao.DeptConfig.Columns().GroupName, in.GroupName).
		Where(dao.DeptConfig.Columns().ConfigKey, in.ConfigKey).
		Count()

	if count > 0 {
		return 0, errors.New("该部门配置已存在")
	}

	// 插入配置记录
	result, err := dao.DeptConfig.Ctx(ctx).Insert(in)
	if err != nil {
		return 0, err
	}

	lastid, _ := result.LastInsertId()
	id = uint64(lastid)
	return id, nil
}

// Upt 更新部门配置
func (*sDeptConfig) Upt(ctx context.Context, in *entity.DeptConfig) (err error) {
	// 检查配置是否存在
	count, _ := dao.DeptConfig.Ctx(ctx).WherePri(in.Id).Count()
	if count == 0 {
		return errors.New("部门配置不存在")
	}

	// 检查配置是否已存在
	count, _ = dao.DeptConfig.Ctx(ctx).
		Where(dao.DeptConfig.Columns().DeptId, in.DeptId).
		Where(dao.DeptConfig.Columns().GroupName, in.GroupName).
		Where(dao.DeptConfig.Columns().ConfigKey, in.ConfigKey).
		Where(dao.DeptConfig.Columns().Id, "!=", in.Id).
		Count()

	if count > 0 {
		return errors.New("该部门配置已存在")
	}

	// 更新配置记录
	_, err = dao.DeptConfig.Ctx(ctx).WherePri(in.Id).OmitNilData().Data(in).Update()
	return
}

// GetPageLst 分页获取部门配置列表
func (*sDeptConfig) GetPageLst(ctx context.Context, in *api.PageLstReq) (out *api.PageLstRes[*entity.DeptConfig], err error) {
	out = &api.PageLstRes[*entity.DeptConfig]{}
	m := dao.DeptConfig.Ctx(ctx).Safe(true)

	// 部门ID筛选
	if deptId := in.Wheres.Get("deptId"); !deptId.IsNil() {
		m = m.Where(dao.DeptConfig.Columns().DeptId, deptId.Uint64())
	}

	// 配置组名筛选
	if groupName := in.Wheres.Get("groupName"); !groupName.IsNil() {
		m = m.Where(dao.DeptConfig.Columns().GroupName, groupName.String())
	}

	// 配置键筛选
	if configKey := in.Wheres.Get("configKey"); !configKey.IsNil() {
		m = m.Where(dao.DeptConfig.Columns().ConfigKey, configKey.String())
	}

	// 分页查询
	err = m.Offset(in.Offset()).Limit(in.Limit()).ScanAndCount(&out.List, &out.Total, false)
	return
}

// Del 删除部门配置
func (*sDeptConfig) Del(ctx context.Context, id uint64) (err error) {
	// 先查询配置信息
	config := &entity.DeptConfig{}
	err = dao.DeptConfig.Ctx(ctx).WherePri(id).Scan(config)
	if err != nil || config.Id == 0 {
		return errors.New("部门配置不存在")
	}
	// 删除缓存
	cacheKey := cacheConsts.GetDeptConfigKey(config.DeptId, config.GroupName, config.ConfigKey)
	_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)
	// 删除配置
	_, err = dao.DeptConfig.Ctx(ctx).WherePri(id).Delete()
	return
}

// GetOne 获取单个部门配置
func (*sDeptConfig) GetOne(ctx context.Context, id uint64) (out *entity.DeptConfig, err error) {
	out = &entity.DeptConfig{}
	err = dao.DeptConfig.Ctx(ctx).WherePri(id).Scan(&out)
	return
}

// GetByDept 按部门获取配置
func (*sDeptConfig) GetByDept(ctx context.Context, deptId uint64, groupName string) (out []*entity.DeptConfig, err error) {
	m := dao.DeptConfig.Ctx(ctx).Where(dao.DeptConfig.Columns().DeptId, deptId)

	// 配置组名筛选
	if groupName != "" {
		m = m.Where(dao.DeptConfig.Columns().GroupName, groupName)
	}

	err = m.Scan(&out)
	return
}

// GetGroupConfigs 获取部门配置组
func (*sDeptConfig) GetGroupConfigs(ctx context.Context, in *v1.GetDeptGroupConfigsReq) (out *v1.GetDeptGroupConfigsRes, err error) {
	out = &v1.GetDeptGroupConfigsRes{}
	out.Configs = make([]*entity.DeptConfig, 0)
	// 查询配置项
	err = dao.DeptConfig.Ctx(ctx).
		Where(dao.DeptConfig.Columns().DeptId, in.DeptId).
		Where(dao.DeptConfig.Columns().GroupName, in.GroupName).
		Order(dao.DeptConfig.Columns().Id).
		Scan(&out.Configs)
	if err != nil {
		return nil, err
	}

	// 获取最新更新时间
	if len(out.Configs) > 0 {
		latestTime := out.Configs[0].UpdatedAt
		for _, item := range out.Configs {
			if item.UpdatedAt.After(latestTime) {
				latestTime = item.UpdatedAt
			}
		}
		out.UpdatedAt = latestTime.Format("2006-01-02 15:04:05")
	}

	return out, nil
}

// SetGroupConfigs 保存部门配置组
func (*sDeptConfig) SetGroupConfigs(ctx context.Context, in *v1.SetDeptGroupConfigsReq) (err error) {
	// 使用事务确保数据一致性
	tx, err := g.DB().Begin(ctx)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	// 删除部门下指定组的现有配置
	_, err = dao.DeptConfig.Ctx(ctx).
		TX(tx).
		Where(dao.DeptConfig.Columns().DeptId, in.DeptId).
		Where(dao.DeptConfig.Columns().GroupName, in.GroupName).
		Delete()
	if err != nil {
		return err
	}

	// 批量添加新配置
	for _, item := range in.Configs {
		// 唯一性校验
		exists, err := dao.DeptConfig.Ctx(ctx).
			TX(tx).
			Where(g.Map{
				dao.DeptConfig.Columns().DeptId:    in.DeptId,
				dao.DeptConfig.Columns().GroupName: in.GroupName,
				dao.DeptConfig.Columns().ConfigKey: item.ConfigKey,
			}).Count()
		if err != nil {
			return err
		}
		if exists > 0 {
			return errors.New(fmt.Sprintf("配置键 %s 已存在", item.ConfigKey))
		}

		// 插入新配置
		_, err = dao.DeptConfig.Ctx(ctx).TX(tx).Insert(&entity.DeptConfig{
			DeptId:      int64(in.DeptId),
			GroupName:   in.GroupName,
			ConfigKey:   item.ConfigKey,
			ConfigValue: item.ConfigValue,
			Remark:      item.ConfigDesc,
			CreatedAt:   gtime.Now(),
			UpdatedAt:   gtime.Now(),
		})
		if err != nil {
			return err
		}
		cacheKey := cacheConsts.GetDeptConfigKey(int64(in.DeptId), in.GroupName, item.ConfigKey)
		_ = service.GetCacheInstance().Set(ctx, cacheKey, item.ConfigValue, 0)
	}

	return nil
}

// GetConfigByKey 根据部门ID、分组名和键名获取配置（优先从缓存读取）
func (*sDeptConfig) GetConfigByKey(ctx context.Context, deptId int64, groupName string, configKey string) (configValue string, err error) {
	cacheKey := cacheConsts.GetDeptConfigKey(deptId, groupName, configKey)
	// 先从缓存读取
	if v, err := service.GetCacheInstance().Get(ctx, cacheKey); err == nil && !v.IsEmpty() {
		return v.String(), nil
	}

	// 缓存未命中则查数据库
	config := new(entity.DeptConfig)
	err = dao.DeptConfig.Ctx(ctx).
		Where(dao.DeptConfig.Columns().DeptId, deptId).
		Where(dao.DeptConfig.Columns().GroupName, groupName).
		Where(dao.DeptConfig.Columns().ConfigKey, configKey).
		Scan(&config)

	if err != nil || config.Id == 0 {
		return "", errors.New("配置不存在")
	}

	// 设置缓存
	_ = service.GetCacheInstance().Set(ctx, cacheKey, config.ConfigValue, 0)

	return config.ConfigValue, nil
}
